<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8">
<meta name="viewport"
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">

    <meta name="author" content="xxx">




    <meta name="keywords" content="博客">




<title>zookeeper | 小站</title>



    <link rel="icon" href="/favicon.ico">



<style>
    @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&family=Roboto+Mono&display=swap');
</style>



    <!-- stylesheets list from _config.yml -->
    
    <link rel="stylesheet" href="/css/style.css">
    




    <!-- scripts list from _config.yml -->
    
    <script src="/js/frame.js"></script>
    







    <script src='https://unpkg.com/valine@1.4.16/dist/Valine.min.js'></script>




  <meta name="generator" content="Hexo 6.0.0"></head>
  <body>
    <div class="mask-border">
    </div>

    <div class="wrapper">

      <div class="header">
  <div class="flex-container">
    <div class="header-inner">
      <div class="site-brand-container">
        <a href="/">
          
            Wudiguang.
          
        </a>
      </div>
      <div id="menu-btn" class="menu-btn" onclick="toggleMenu()">
        Menu
      </div>
      <nav class="site-nav">
        <ul class="menu-list">
          
            
              <li class="menu-item">
                <a href="/">Home</a>
              </li> 
                   
          
            
              <li class="menu-item">
                <a href="/tag/">标签</a>
              </li> 
                   
          
            
              <li class="menu-item">
                <a href="/archives/">时间线</a>
              </li> 
                   
          
            
              <li class="menu-item">
                <a href="/categories/gallery/">展览馆</a>
              </li> 
                   
          
            
              <li class="menu-item">
                <a href="/comment/">留言</a>
              </li> 
                   
          
        </ul>
      </nav>
    </div>
  </div>
</div>


      <div class="main">
        <div class="flex-container">
          <article id="post">

  
    <div class="post-head">
    <div class="post-info">
        <div class="tag-list">
            
                
                    <span class="post-tag">
                        <a href="/tags/%E5%88%86%E5%B8%83%E5%BC%8F/">
                            分布式
                        </a>
                    </span>    
                
                    <span class="post-tag">
                        <a href="/tags/zookeeper/">
                            zookeeper
                        </a>
                    </span>    
                           
            
        </div>
        <div class="post-title">
            
            
                zookeeper
            
            
        </div>
        <span class="post-date">
            8月 5, 2021
        </span>
    </div>
    <div class="post-img">
        
            <div class="h-line-primary"></div>
              
    </div>
</div>
    <div class="post-content">
    <h2 id="一、zookeeper-入门"><a href="#一、zookeeper-入门" class="headerlink" title="一、zookeeper 入门"></a>一、zookeeper 入门</h2><h3 id="1-1-zookeeper-概述"><a href="#1-1-zookeeper-概述" class="headerlink" title="1.1 zookeeper 概述"></a>1.1 zookeeper 概述</h3><blockquote>
<p>zk 是一个开源的分布式协调服务，将复杂且容易出错的分布式一致性服务封装起来，构成一个高效可靠的原语集，提供给用户使用</p>
</blockquote>
<p>zk 提供了高可用、高性能、稳定的分布式数据一致性解决方案。通常被用于实现数据发布&#x2F;订阅、负载均衡、命名服务、分布式协调&#x2F;通知、集群管理、master 选举、分布式锁和分布式队列等功能</p>
<p>另外，zk 将数据保存在内存中，性能很nice</p>
<h3 id="1-2-zk-特点"><a href="#1-2-zk-特点" class="headerlink" title="1.2 zk 特点"></a>1.2 zk 特点</h3><ul>
<li>顺序一致性：客户端发起的事务，按照顺序被应用到 zk 中</li>
<li>原子性：事务请求，对集群中所有的及其应用情况是一样的，要么都成功，要么都失败</li>
<li>单一系统映像：zk 集群保证查询到的数据都是一致的</li>
<li>可靠性：一旦更改请求被应用，数据将持久化</li>
</ul>
<span id="more"></span>

<h3 id="1-3-应用场景"><a href="#1-3-应用场景" class="headerlink" title="1.3 应用场景"></a>1.3 应用场景</h3><ul>
<li>分布式锁：通过创建唯一节点获得分布式锁，当获得锁的一方执行完或者挂掉后就释放锁</li>
<li>命名服务：通过 zk 的顺序节点生成全局唯一 ID</li>
<li>数据发布&#x2F;订阅：通过 Watch 机制，实现数据发布&#x2F;订阅。数据被发布到 zk 的被监听的节点上，其他及其可以通过监听该节点来实现配置的动态更新</li>
</ul>
<blockquote>
<p>开源项目使用 zk：kafka、hbase、hadoop</p>
</blockquote>
<h2 id="二、zk-重点"><a href="#二、zk-重点" class="headerlink" title="二、zk 重点"></a>二、zk 重点</h2><blockquote>
<p>zk 主要是用来协调服务的，不是用来存储业务数据的，不能将大数据放在 zk 中</p>
</blockquote>
<h3 id="2-1-Data-model（数据模型）"><a href="#2-1-Data-model（数据模型）" class="headerlink" title="2.1 Data model（数据模型）"></a>2.1 Data model（数据模型）</h3><blockquote>
<p>类 Linux 系统中文件系统，树形结构</p>
</blockquote>
<h3 id="2-2-znode（数据节点）"><a href="#2-2-znode（数据节点）" class="headerlink" title="2.2 znode（数据节点）"></a>2.2 znode（数据节点）</h3><blockquote>
<p>zk 中最小数据单位</p>
</blockquote>
<ul>
<li>持久节点：持久化，直到被删除</li>
<li>临时节点：生命周期为 和客户端绑定（session），会话消失则节点被删除，临时节点只能做叶子节点，不能创建子节点</li>
<li>持久顺序节点：有序（如 &#x2F;node1&#x2F;app000000001）</li>
<li>临时顺序节点：有序</li>
</ul>
<p>znode 数据结构</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;stat&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;状态信息&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;data&quot;</span> <span class="punctuation">:</span> <span class="string">&quot;节点存放的内容&quot;</span>   </span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure>

<p><strong>stat 中数据信息</strong></p>
<p>cZxid:create ZXID，即该数据节点被创建时的事务 id<br>ctime:create time，即该节点的创建时间<br>mZxid:modified ZXID，即该节点最终一次更新时的事务 id<br>mtime:modified time，即该节点最后一次的更新时间<br>pZxid:该节点的子节点列表最后一次修改时的事务 id，只有子节点列表变更才会更新 pZxid，子节点内容变更不会更新<br>cversion:子节点版本号，当前节点的子节点每次变化时值增加 1<br>dataVersion:数据节点内容版本号，节点创建时为 0，每更新一次节点内容(不管内容有无变化)该版本号的值增加 1<br>aclVersion:节点的 ACL 版本号，表示该节点 ACL 信息变更次数<br>ephemeralOwner:创建该临时节点的会话的 sessionId；如果当前节点为持久节点，则 ephemeralOwner&#x3D;0<br>dataLength:数据节点内容长度<br>numChildren:当前节点的子节点个数</p>
<h3 id="2-3-ACL（权限控制）"><a href="#2-3-ACL（权限控制）" class="headerlink" title="2.3 ACL（权限控制）"></a>2.3 ACL（权限控制）</h3><p>对于 znode 的操作权限</p>
<ul>
<li>CREATE：支持创建子节点</li>
<li>READ：能查询节点数据和列出子节点</li>
<li>WRITE：能设置&#x2F;更新节点数据</li>
<li>DELETE：能删除子节点</li>
<li>ADMIN：能设置节点 ACL 的权限</li>
</ul>
<p><code>CREATE 和 DELETE 都是对子节点的控制权限</code><br> 对于身份认证，提供以下几种方式：</p>
<ul>
<li>world：默认，any user can use</li>
<li>auth：任何已认证用户</li>
<li>digest： username：password</li>
<li>ip：对指定 IP 限制</li>
</ul>
<h3 id="2-4-Watcher（事件监听器）"><a href="#2-4-Watcher（事件监听器）" class="headerlink" title="2.4 Watcher（事件监听器）"></a>2.4 Watcher（事件监听器）</h3><blockquote>
<p>允许节点注册 Watch，在某些特定事件触发时，zk 服务端会将事件通知到感兴趣的客户端</p>
</blockquote>
<h3 id="2-5-Session（会话）"><a href="#2-5-Session（会话）" class="headerlink" title="2.5 Session（会话）"></a>2.5 Session（会话）</h3><blockquote>
<p>可以看作是 zk 与客户端之间的 TCP 长连接</p>
</blockquote>
<p>Session：sessionTimeout 会话超时时间（范围内，仍属于同一个 session）<br>zk 与客户端创建 session 之前，会为客户端分配一个 sessionID，全局唯一</p>
<h2 id="三、zk-集群"><a href="#三、zk-集群" class="headerlink" title="三、zk 集群"></a>三、zk 集群</h2><blockquote>
<p>为了保证高可用，zk 需集群部署，只要集群中大部分机器可用，则集群可用。集群间通过 ZAB（zk Atomic Broadcase） 保证数据一致性</p>
</blockquote>
<p>典型集群模式：Master&#x2F;Slave（主从模式）</p>
<h3 id="3-1-zk-集群中角色"><a href="#3-1-zk-集群中角色" class="headerlink" title="3.1 zk 集群中角色"></a>3.1 zk 集群中角色</h3><blockquote>
<p>Leader,Follower,Observer</p>
</blockquote>
<ul>
<li>Leader：提供读写，负责投票的发起和决议，更新系统状态</li>
<li>Follower：提供读，参与选举投票，转发写请求给 Leader</li>
<li>Observer：提供读，不参与 Leader 选举</li>
</ul>
<p><strong>leader写数据</strong></p>
<p><strong>读数据</strong></p>
<p>当 Leader 服务器出现网络中断、崩溃退出与重启等异常情况，就会进入 Leader 选举过程</p>
<ol>
<li>Leader election（选举阶段）：只要一个节点得到超过半数节点的票数，则可成为 Leader</li>
<li>Discovery（发现阶段）：Follower 与准 Leader 通信，同步 Follower 最近接收的事务提议</li>
<li>Synchronization（同步阶段）：利用 Leader 前一阶段获得的最新提议历史，同步集群所有的副本。同步完成准 Leader 成为 Leader</li>
<li>Broadcase（广播阶段）：zk 集群正式对外提供事务服务，Leader 可以进行消息广播。若有新节点加入，需对新节点进行同步</li>
</ol>
<h3 id="3-2-zk-集群中服务状态"><a href="#3-2-zk-集群中服务状态" class="headerlink" title="3.2 zk 集群中服务状态"></a>3.2 zk 集群中服务状态</h3><ul>
<li>LOOKING：寻找 Leader</li>
<li>LEADING：Leader 状态，对应的节点为 Leader</li>
<li>FOLLOWING：Follower 状态，对应节点为 Follower</li>
<li>OBSERVING：Observer 状态，对应节点为 Observer，不参与 Leader 选举</li>
</ul>
<h3 id="3-3-zk-集群数量"><a href="#3-3-zk-集群数量" class="headerlink" title="3.3 zk 集群数量"></a>3.3 zk 集群数量</h3><blockquote>
<p>zk 集群，服务器剩余数量大于宕机数量才能继续提供服务。即 2n 和 2n-1 的容忍度是一样的</p>
</blockquote>
<h3 id="3-4-zk-选举的过半机制防止脑裂"><a href="#3-4-zk-选举的过半机制防止脑裂" class="headerlink" title="3.4 zk 选举的过半机制防止脑裂"></a>3.4 zk 选举的过半机制防止脑裂</h3><blockquote>
<p>为保证 zk 集群可用性，服务器通常部署在不同机房，如果机房间网络线路故障，集群被割裂成几个小集群</p>
</blockquote>
<p>过半机制防止脑裂：服务器少于等于一般不可能产生 Leader</p>
<h2 id="四、ZAB-协议和-Paxos-算法"><a href="#四、ZAB-协议和-Paxos-算法" class="headerlink" title="四、ZAB 协议和 Paxos 算法"></a>四、ZAB 协议和 Paxos 算法</h2><h3 id="4-1-ZAB-协议简介"><a href="#4-1-ZAB-协议简介" class="headerlink" title="4.1 ZAB 协议简介"></a>4.1 ZAB 协议简介</h3><blockquote>
<p>ZAB（zk Atomic Broadcast 原子广播）协议是 zk 专门设计的一种支持崩溃恢复的原子广播协议。zk 中主要依赖 ZAB 协议来实现分布式数据一致性，基于该协议，zk 实现了一种主备模式的系统架构来保持集群中各个副本之间数据一致性</p>
</blockquote>
<p>ZAB 协议两种基本的模式：崩溃恢复和消息广播</p>
<ul>
<li>崩溃恢复：当服务框架在启动过程中，或是当 Leader 服务器出现网络中断、崩溃退出与重启等异常时，ZAB 协议就会进入恢复模式并选举新的 Leader。当选举产生了新的 Leader，切已经有过半的机器与 Leader 完成了状态同步后，ZAB 协议就会退出恢复模式。状态同步即数据同步，用来保证集群中存在过半的及其的数据与 Leader 一致</li>
<li>消息广播：当一台遵守 ZAB 协议的服务器启动后加入到集群中时，如果此时集群中已经存在 Leader 在负责进行消息广播，则新加入的服务器会自觉进入数据恢复模式，找到 Leader，进行数据同步</li>
</ul>
<p><strong>选举算法：FastLeaderElection</strong></p>
<ul>
<li>myid：每个 zk 服务器在数据文件夹下创建名为 myid 的文件，内容全局唯一整数 ID</li>
</ul>
<h2 id="五、常用命令"><a href="#五、常用命令" class="headerlink" title="五、常用命令"></a>五、常用命令</h2><ol>
<li>help</li>
<li>create</li>
<li>set</li>
<li>get</li>
<li>ls</li>
<li>stat</li>
<li>ls2（ls + stat）</li>
<li>delete</li>
</ol>
<h2 id="六、总结"><a href="#六、总结" class="headerlink" title="六、总结"></a>六、总结</h2><ol>
<li>zk 是分布式程序（半数以上节点存活则 zk 能正常提供服务）</li>
<li>zk 数据保存在内存中</li>
<li>zk 是高性能</li>
<li>zk 中持久节点&amp;临时节点</li>
<li>zk 底层提供两个功能：管理（存取）程序数据、为用户提供数据节点的监听</li>
</ol>

</div> 

<script>
    window.onload = detectors();
</script>
    <div class="post-footer">
    <div class="h-line-primary"></div>
    <nav class="post-nav">
        <div class="prev-item">
           
                <div class="icon arrow-left"></div>
                <div class="post-link">
                    <a href="/2021/12/25/react/">Prev</a>
                </div>
            
        </div>
        <div class="next-item">
            
                <div class="icon arrow-right"></div>
                <div class="post-link">
                  <a href="/2021/08/03/redis/">Next</a>  
                </div>  
            
        </div>
    </nav>
</div>

    
      <div class="post-comment">

    
        <div id="vcomments"></div>
        <script>
            var META = ['nick', 'mail', 'link'];
            var meta = 'nick,mail';
            meta = meta.split(',').filter(item => {
                return META.includes(item);
            });
            new Valine({
                el: '#vcomments',
                appId: 'X7Jbrh9MUCMJpzODTOJJImgc-gzGzoHsz',
                appKey: 'ALE0H1nS33YlJtDpquuDHFPz',
                lang: 'en',
                placeholder: 'Say something',
                avatar: 'mp',
                meta: meta
            })
        </script>    
     

     
    
    

</div>
     
  
</article>
        </div>
      </div>
      
      <div class="footer">
    <div class="flex-container">
        <div class="footer-text">
            
            
            
                Powered by <a target="_blank" rel="noopener" href="https://hexo.io/">Hexo</a> & <a target="_blank" rel="noopener" href="https://github.com/zoeingwingkei/frame/">Frame</a>
                
        </div>
    </div>
</div>

    </div>

  </body>
</html>
